﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace DirectoryWatcher
{
    public partial class Form1 : Form
    {

        Thread[] Thread = null;
        Watcher[] Watcher = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void btn_AddDirectory_Click(object sender, EventArgs e)
        {
            if (this.folderBrowserDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            this.listBox1.Items.Add(this.folderBrowserDialog1.SelectedPath);
        }

        private void btn_Delete_Click(object sender, EventArgs e)
        {
            if (this.listBox1.SelectedItems != null)
            {
                while (this.listBox1.SelectedItems.Count > 0)
                {
                    this.listBox1.Items.Remove(this.listBox1.SelectedItems[0]);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.listBox1.Items.Count < 1)
            {
                MessageBox.Show("请选择监控的文件夹");
                return;
            }

            Thread = new Thread[this.listBox1.Items.Count];
            Watcher = new Watcher[this.listBox1.Items.Count];

            this.button1.Enabled = false;
            this.button2.Enabled = true;

            for (int i = 0; i < Thread.Length; i++)
            {
                Watcher[i] = new Watcher(this.listBox1.Items[i].ToString(), this);
                Thread[i] = new Thread(new ThreadStart(Watcher[i].Start));
                Thread[i].Start();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.button1.Enabled = true;
            this.button2.Enabled = false;

            for (int i = 0; i < Thread.Length; i++)
            {
                Watcher[i].Stop();
                Thread[i].Abort();
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;

            if (Watcher == null)
            {
                e.Cancel = false;
                return;
            }

            for (int i = 0; i < Watcher.Length; i++)
            {
                if (Watcher[i].IsAlive)
                {
                   DialogResult result=  MessageBox.Show("正在进行监控文件夹，确认要关闭吗？","系统提示",MessageBoxButtons.OKCancel,MessageBoxIcon.Information);
                   if (result == DialogResult.Cancel)
                   {
                       return;
                   }
                }
            }

            e.Cancel = false;
        }

        private void tbKeyword_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;

            if (!Regex.IsMatch(e.KeyChar.ToString(), @"^[A-Za-z0-9\.\*\-]$"))
            {
                MessageBox.Show("文件夹只能包含字母、数字、点(.)、星号(*)、连接线(-)");
                return;
            }

            e.Handled = false;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "文本文件(*.txt)|*.txt|日志文件(*.log)|*.log|所有文件(*.*)|*.*";
            this.saveFileDialog1.FilterIndex = 2;
            this.saveFileDialog1.DefaultExt="log";
            this.saveFileDialog1.FileName="watcher";
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            try
            {
                this.richTextBox1.SaveFile(this.saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
                MessageBox.Show("保存成功");
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

    public class Watcher
    {
        #region Attributes

        private string t_Directory = "";
        private Form1 t_obj;
        private FileSystemWatcher FileWatcher = new FileSystemWatcher();
        private delegate void DeleGate(string txt);

        private bool t_isalive = false;
        public bool IsAlive
        {
            get { return t_isalive; }
        }
        

        #endregion

        public Watcher()
        {
        }

        public Watcher(string Dir, Form1 obj)
        {
            t_Directory = Dir;
            t_obj = obj;
        }

        public void Start()
        {
            if (!Directory.Exists(t_Directory))
            {
                t_obj.richTextBox1.Invoke(new DeleGate(outTxt), new object[] { DateTime.Now.ToString() + " 监控点：" + t_Directory + "不存在\n" });
                return;
            }

            WatcherThread();
            this.t_isalive = true;
            t_obj.richTextBox1.Invoke(new DeleGate(outTxt), new object[] { DateTime.Now.ToString() + " 开始监控文件夹 " + t_Directory + "\n" });
        }

        public void Stop()
        {
            FileWatcher.EnableRaisingEvents = false;
            this.t_isalive = false;
            t_obj.richTextBox1.Invoke(new DeleGate(outTxt), new object[] { DateTime.Now.ToString() + " 停止监控文件夹 " + t_Directory + "\n" });
        }

        protected void WatcherThread()
        {
            FileWatcher.Path = t_Directory;

            if (t_obj.CheckSubDir.Checked) FileWatcher.IncludeSubdirectories = true;

            FileWatcher.Filter = t_obj.tbKeyword.Text.Length == 0 ? "*.*" : t_obj.tbKeyword.Text;

            if (t_obj.CheckDirectoryName.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.DirectoryName;
            if (t_obj.CheckFileName.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.FileName;
            if (t_obj.CheckCreationTime.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.CreationTime;
            if (t_obj.CheckLastAccess.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.LastAccess;
            if (t_obj.CheckLastWrite.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.LastWrite;
            if (t_obj.CheckSecurity.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.Security;
            if (t_obj.CheckAttributes.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.Attributes;
            if (t_obj.CheckSize.Checked) FileWatcher.NotifyFilter = FileWatcher.NotifyFilter | NotifyFilters.Size;

            if (t_obj.CheckCreate.Checked) FileWatcher.Changed += new FileSystemEventHandler(OnChanged);
            if (t_obj.CheckChange.Checked) FileWatcher.Created += new FileSystemEventHandler(OnChanged);
            if (t_obj.CheckDelete.Checked) FileWatcher.Deleted += new FileSystemEventHandler(OnChanged);
            if (t_obj.CheckRename.Checked) FileWatcher.Renamed += new RenamedEventHandler(Renamed);

            FileWatcher.EnableRaisingEvents = true;
        }

        protected void OnChanged(object source, FileSystemEventArgs e)
        {
            t_obj.richTextBox1.Invoke(new DeleGate(outTxt), new object[] { DateTime.Now.ToString() + " " + e.ChangeType + " " + e.FullPath + "(监控点：" + t_Directory + ")\n" });
        }

        protected void Renamed(object source, RenamedEventArgs e)
        {
            t_obj.richTextBox1.Invoke(new DeleGate(outTxt), new object[] { DateTime.Now.ToString() + " " + e.ChangeType + " " + e.OldFullPath + " → " + e.FullPath + "(监控点：" + t_Directory + ")\n" });
        }

        protected void outTxt(string txt)
        {
            t_obj.richTextBox1.AppendText(txt);
        }
    }
}
